package cn.csc.module.order.controller.app.order;

import cn.csc.framework.common.pojo.CommonResult;
import cn.csc.framework.common.pojo.PageResult;
import cn.csc.framework.common.util.collection.CollectionUtils;
import cn.csc.framework.common.util.json.JsonUtils;
import cn.csc.framework.common.util.servlet.ServletUtils;
import cn.csc.module.member.api.address.MemberAddressApi;
import cn.csc.module.member.api.address.dto.MemberAddressRespDTO;
import cn.csc.module.member.api.user.MemberUserApi;
import cn.csc.module.member.api.user.dto.MemberUserRespDTO;
import cn.csc.module.order.controller.admin.addr.vo.OrderAddrBaseVO;
import cn.csc.module.order.controller.admin.item.vo.OrderItemBaseVO;
import cn.csc.module.order.controller.admin.order.vo.LogisticsVO;
import cn.csc.module.order.controller.admin.order.vo.OrderPageReqVO;
import cn.csc.module.order.controller.admin.order.vo.OrderUpdateDeliveryReqVO;
import cn.csc.module.order.controller.admin.order.vo.OrderWithItemAndAddrRespVO;
import cn.csc.module.order.controller.app.dto.OrderToPayReqDTO;
import cn.csc.module.order.controller.app.order.vo.*;
import cn.csc.module.order.controller.app.vo.OrderAddrVO;
import cn.csc.module.order.controller.app.vo.OrderRespVO;
import cn.csc.module.order.convert.addr.OrderAddrConvert;
import cn.csc.module.order.convert.item.OrderItemConvert;
import cn.csc.module.order.convert.order.OrderConvert;
import cn.csc.module.order.dal.dataobject.addr.OrderAddrDO;
import cn.csc.module.order.dal.dataobject.item.OrderItemDO;
import cn.csc.module.order.dal.dataobject.order.OrderDO;
import cn.csc.module.order.enums.*;
import cn.csc.module.order.mq.producer.OrderReceiptProducer;
import cn.csc.module.order.mq.producer.hzh.OrderReceiptForHzhProducer;
import cn.csc.module.order.service.addr.OrderAddrService;
import cn.csc.module.order.service.item.OrderItemService;
import cn.csc.module.order.service.order.OrderService;
import cn.csc.module.order.service.shopcart.ShopCartItemService;
import cn.csc.module.order.util.Kuaidi100Util;
import cn.csc.module.pay.api.order.PayOrderApi;
import cn.csc.module.pay.api.order.dto.CreateDivideWithOrderItemIdReqDTO;
import cn.csc.module.pay.api.order.dto.PayOrderCreateReqDTO;
import cn.csc.module.product.api.sku.SkuApi;
import cn.csc.module.product.api.sku.dto.SkuDTO;
import cn.csc.module.product.api.spu.SpuApi;
import cn.csc.module.product.api.spu.dto.SpuDTO;
import cn.csc.module.product.api.stocklock.SkuStockLockApi;
import cn.csc.module.product.api.stocklock.dto.SkuStockDTO;
import cn.csc.module.shop.api.detail.ShopDetailApi;
import cn.csc.module.shop.api.detail.dto.ShopDetailRespDTO;
import cn.csc.module.shoppingCard.api.card.CardApi;
import cn.csc.module.shoppingCard.api.card.dto.CardRespDTO;
import cn.csc.module.shoppingCard.api.transaction.CardTransactionApi;
import cn.csc.module.shoppingCard.api.transaction.dto.CardTransactionRespDTO;
import cn.csc.module.system.api.ip.KuaiDi100CompanyCodeApi;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.kuaidi100.sdk.pojo.HttpResult;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static cn.csc.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.csc.framework.common.pojo.CommonResult.error;
import static cn.csc.framework.common.pojo.CommonResult.success;
import static cn.csc.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.csc.module.order.enums.ErrorCodeConstants.*;

/**
 * 订单Controller
 * 万商汇、选品
 * @author liuchuang
 * @version 1.0
 * @modify
 * @since 2024/11/22 17:16
 */
@RestController
@RequestMapping("/order/v2")
@Tag(name = "app-订单信息")
@Slf4j
public class AppOrderV2Controller {

    @Autowired
    private OrderService orderService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SkuApi skuApi;
    @Autowired
    private SpuApi spuApi;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private ShopDetailApi shopDetailApi;
    @Autowired
    private PayOrderApi payOrderApi;
    @Autowired
    private OrderReceiptProducer orderReceiptProducer;
    @Autowired
    private OrderReceiptForHzhProducer orderReceiptForHzhProducer;

    @Value("${csc.pay.appId}")
    private BigInteger appId;
    @Value("${csc.wanshanghui.tradeLimit}")
    private BigDecimal tradeLimit;

    @Resource
    private MemberUserApi memberUserApi;
    @Autowired
    private OrderAddrService orderAddrService;
    @Autowired
    private MemberAddressApi memberAddressApi;
    @Autowired
    private ShopCartItemService shopCartItemService;
    @Autowired
    private SkuStockLockApi skuStockLockApi;
    @Autowired
    private CardApi cardApi;
    @Autowired
    private CardTransactionApi cardTransactionApi;
    @Autowired
    private KuaiDi100CompanyCodeApi kuaiDi100CompanyCodeApi;
    @Value("${csc.wl.kuaidi100.customer}")
    private String customer;
    @Value("${csc.wl.kuaidi100.key}")
    private String key ;
    /**
     * 生成订单（多个sku）
     *
     * @return
     */
    @GlobalTransactional(name = "csc-order-confirm", rollbackFor = Exception.class)
    @PostMapping("/confirm")
    @Operation(summary = "结算，生成订单信息", description = "传入下单所需要的参数进行下单")
    public CommonResult<BigInteger> confirm(@Valid @RequestBody AppOrderCreateReqVO reqVO) {
        log.info("[AppOrderV2Controller][confirm][reqVO]{}",reqVO);
        if (reqVO.getOrderId() != null){
            // 获取订单缓存 , orderId:orderAddrId:allCount
            Object orderCache = redisTemplate.opsForValue().get(OrderCacheNames.ORDER_CONFIRM_KEY + reqVO.getOrderId()
                    + CacheNames.UNION_KEY + reqVO.getOrderAddrId() + CacheNames.UNION_KEY + reqVO.getAllCount() );
            if (orderCache != null) {
                throw exception(ORDER_SUBMIT_DUPLICATE);
            }
        }
        //判断商品是否下架
        List<SpuDTO> spuDTOList = spuApi.getSpuList(reqVO.getOrderItems().stream().map(AppOrderItemCreateReqVO::getSpuId).collect(Collectors.toList())).getCheckedData();
        log.info("[AppOrderV2Controller][confirm][spuDTOList]{}",spuDTOList);
        log.info("[AppOrderV2Controller][confirm][spuDTOList]{}",spuDTOList.stream().filter(c -> c.getVerifyStatus()!=10).collect(Collectors.toList()));
        if(spuDTOList.stream().anyMatch(c -> c.getVerifyStatus() != 10))//产品已下架
            throw exception(ORDER_PRODUCT_NOT_EXISTS);

        //判断库存是否充足
        List<BigInteger> skuIds=reqVO.getOrderItems().stream().map(AppOrderItemCreateReqVO::getSkuId).collect(Collectors.toList());
        log.info("[AppOrderV2Controller][confirm][skuIds]{}",skuIds);
        List<SkuStockDTO> skuStockList=skuStockLockApi.getSkuStockList(skuIds).getCheckedData();
        log.info("[AppOrderV2Controller][confirm][skuStockList]{}",skuStockList);
        // 使用Stream API比较两个列表的对应元素是否满足条件
        boolean areEqual = IntStream.range(0, Math.min(skuStockList.size(),reqVO.getOrderItems().size() ))
                .allMatch(i -> ( skuStockList.get(i).getStock() - reqVO.getOrderItems().get(i).getCount() < 0));
        if(areEqual)
            throw exception(ORDER_PRODUCT_STOCK_EXISTS);


        // 重算一遍订单金额
        //是否是供应商，供应商取供应商价格
        MemberUserRespDTO memberUserRespDTO = memberUserApi.getUser(getLoginUserId()).getData();
        log.info("[AppOrderV2Controller][confirm][memberUserRespDTO]{}",memberUserRespDTO);

        List<SkuDTO> skuList = skuApi.getSkuList(skuIds).getCheckedData();
        Map<BigInteger, SkuDTO> skuMap = CollectionUtils.convertMap(skuList, SkuDTO::getId);
        int userType = memberUserRespDTO != null ? memberUserRespDTO.getType() : 0;
        // 查询产品服务后计算的订单总金额
        BigDecimal total = reqVO.getOrderItems().stream().map(oi -> {
            BigDecimal productPrice = userType == 5 || userType==15  ? skuMap.get(oi.getSkuId()).getShopPriceFee()
                    : skuMap.get(oi.getSkuId()).getPriceFee();
            return productPrice.multiply(BigDecimal.valueOf(oi.getCount()));
        }).reduce(BigDecimal.ZERO, BigDecimal::add);


        //订单金额不能超过50000元
        if (total.compareTo(tradeLimit) > 0) {
            return CommonResult.error(ErrorCodeConstants.ORDER_AMT_MAX_EXISTS);
        }
        //是否使用购物卡，是：等比例拆分购物卡金额到个个sku订单
        if(reqVO.getCardIds()!=null && !reqVO.getCardIds().isEmpty()){
            log.info("[AppOrderV2Controller][confirm]reqVO.getCardIds(): {}", reqVO.getCardIds());
            List<CardRespDTO> cardList=cardApi.listByCardId(reqVO.getCardIds()).getCheckedData();
            log.info("[AppOrderV2Controller][confirm]cardList: {}", cardList);
            reqVO.setCardList(cardList);
            BigDecimal giftCardAmount =cardList.stream().map(CardRespDTO::getBalance).reduce(BigDecimal.ZERO, BigDecimal::add);

            //判断购物卡金额是否可以覆盖订单金额
            if(giftCardAmount.compareTo(total) >0){
                reqVO.setPayType(1);// 购物卡支付
                reqVO.setActualAmount(new BigDecimal(0));
            }else{
                reqVO.setPayType(2);// 结合支付
                reqVO.setActualAmount(total.subtract(giftCardAmount));
                //订单总金额
                log.info("[AppOrderV2Controller][confirm]total: {}", total);
                if (total.subtract(giftCardAmount).compareTo(reqVO.getTotal()) != 0) {
                    return CommonResult.error(ErrorCodeConstants.ORDER_AMT_NOT_EXISTS);
                }
            }
        }else{
            //订单总金额
            log.info("[AppOrderV2Controller][confirm]total: {}", total);
            if (total.compareTo(reqVO.getTotal()) != 0) {
                return CommonResult.error(ErrorCodeConstants.ORDER_AMT_NOT_EXISTS);
            }
            reqVO.setPayType(0);// 微信支付
            reqVO.setActualAmount(total);
        }

        reqVO.setTotal(total);
        reqVO.setUserId(BigInteger.valueOf(getLoginUserId()));
        if(StringUtil.isEmpty(reqVO.getNickName())) {
            reqVO.setNickName("微信用户");
        }

        reqVO.setOrderType(userType==5 || userType==15 ?1:0);
        BigInteger orderId;
        if(reqVO.getOrderId() != null){
            log.info("[AppOrderV2Controller][confirm]订单更新：{}",reqVO.getOrderId());
            orderId = orderService.submitOrderV2(reqVO);
        }else{
            orderId = orderService.saveOrderV2(reqVO);
            log.info("[AppOrderV2Controller][confirm]订单新增：{}",orderId);
        }
        // 缓存，防止重复提交
        redisTemplate.opsForValue().set(OrderCacheNames.ORDER_CONFIRM_KEY + reqVO.getOrderId()+ CacheNames.UNION_KEY
                + reqVO.getOrderAddrId() + CacheNames.UNION_KEY + reqVO.getAllCount(), getLoginUserId(), 30L, TimeUnit.MINUTES);

        return success(orderId);
    }


    /**
     * 这里有提交订单的代码（多个sku）
     * 提交订单,
     */
    @GlobalTransactional(name = "csc-order-toPay", rollbackFor = Exception.class)
    @PostMapping("/toPay")
    @Operation(summary = "提交订单，返回支付流水号", description = "根据传入的参数判断是否为购物车提交订单，同时对购物车进行删除，用户开始进行支付")
    public CommonResult<BigInteger> toPay(@Valid @RequestBody OrderToPayReqDTO reqDTO) {
        log.info("[toPay] 当前 XID: {}", RootContext.getXID());
        OrderDO orderDO = orderService.get(reqDTO.getOrderId());
        if(orderDO==null){
            return CommonResult.error(ErrorCodeConstants.ORDER_NOT_EXISTS);
        }
        List<OrderItemDO> orderItems = orderItemService.getItemByOrderId(reqDTO.getOrderId());
        List<BigInteger> shopIds = orderItems.stream().map(OrderItemDO::getShopId).collect(Collectors.toList());
        log.info("toPay shopIds : {},", JsonUtils.toJsonString(shopIds));
        List<ShopDetailRespDTO> shopDetails = shopDetailApi.getShopDetailList(shopIds).getCheckedData();

        String appUserIds = shopDetails.stream().map(ShopDetailRespDTO::getAppUserId).collect(Collectors.joining(","));
        String shopNames = shopDetails.stream().map(ShopDetailRespDTO::getShopName).collect(Collectors.joining(","));
        String spuNames = orderItems.stream().map(OrderItemDO::getSpuName).collect(Collectors.joining(","));

        PayOrderCreateReqDTO payDTO = new PayOrderCreateReqDTO();
        String no = PayOrderNo.ORDER_NO_PREFIX + IdUtil.getSnowflakeNextId();
        payDTO.setAppId(appId)
                .setAppUserId(appUserIds)//多个商家逗号分隔？
                .setMerchantOrderId(no)
                .setUserIp(ServletUtils.getClientIP())
                .setSubject(shopNames.length() > 32 ? shopNames.substring(0, 32) : shopNames) //多个商家逗号分隔 商品标题不能超过 32
                .setBody(spuNames.length() > 128 ? spuNames.substring(0, 128) : spuNames) //多个商家逗号分隔 商品描述信息长度不能超过128
                .setAmount(orderDO.getActualAmount().multiply(BigDecimal.valueOf(100)).intValue())
                .setCardPayAmount(orderDO.getCardPayAmount()!=null?orderDO.getCardPayAmount().multiply(BigDecimal.valueOf(100)).intValue():null)
                .setExpireTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 30, ChronoUnit.MINUTES))
                .setOrderType(7);  // 5:分账(分账必填,否则走直销) 7:分账(内部订单)
        log.info("[AppOrderV2Controller][toPay][payDTO]=={},",payDTO);
        CommonResult<BigInteger> resultData = payOrderApi.createOrder(payDTO);
        log.info("[AppOrderV2Controller][toPay][resultData]=={},",resultData);
        BigInteger resultId = resultData.getData();
        if(resultId == null){
            return CommonResult.error(ErrorCodeConstants.ORDER_TO_PAY_ERROR);
        }

        log.info("[AppOrderV2Controller][toPay][resultId]=={}",resultId);
        OrderDO updateReqVO =  new OrderDO();
        updateReqVO.setId(orderDO.getId())
                   .setOutTradeNo(resultId.toString())
                   .setMerchantOrderId(no);
        log.info("[AppOrderV2Controller][toPay][updateReqVO]=={}",updateReqVO);
        orderService.updateOrderNo(updateReqVO);

        return success(resultId);
    }
    /**
     * 买家的订单列表
     */
    @GetMapping("/orderList")
    @Operation(summary = "买家的订单列表" , description = "买家的订单列表")
    public CommonResult<PageResult<AppOrderWithItemAndAddrRespVO>> orderList(@Valid OrderPageReqVO pageVO) {
        pageVO.setUserId(BigInteger.valueOf(getLoginUserId()));
        PageResult<OrderWithItemAndAddrRespVO> pageResult = orderService.selectOrderWithItemAndAddrPage(pageVO);
        log.info("orderList : mapper pageResult.getList().size()={} , {}", pageResult.getList().size(), pageResult.getList());
        if (!CollectionUtils.isAnyEmpty(pageResult.getList())){
            List<BigInteger> shopIds = pageResult.getList().stream().map(OrderWithItemAndAddrRespVO::getOrderItems).flatMap(Collection::stream).map(OrderItemBaseVO::getShopId)
                    .distinct().collect(Collectors.toList());
            // 查询店铺信息
            List<ShopDetailRespDTO> shopDetails = shopDetailApi.getShopDetailList(shopIds).getCheckedData();
            Map<BigInteger, String> shopMap = CollectionUtils.convertMap(shopDetails, ShopDetailRespDTO::getId, ShopDetailRespDTO::getShopName);
            pageResult.getList().stream().map(OrderWithItemAndAddrRespVO::getOrderItems).flatMap(Collection::stream)
                    .forEach(o -> o.setShopName(shopMap.get(o.getShopId())));
            log.info("orderList : pageResult.getList().size()={} , {}", pageResult.getList().size(), pageResult.getList());
            List<AppOrderWithItemAndAddrRespVO> records = pageResult.getList().stream().map(o -> {
                AppOrderWithItemAndAddrRespVO convert = OrderConvert.INSTANCE.convert(o);
                convert.setOrderItemMap(CollectionUtils.convertMultiMap(o.getOrderItems(), OrderItemBaseVO::getShopId));
                convert.setOrderAddrMap(CollectionUtils.convertMultiMap(o.getOrderAddrList(), OrderAddrBaseVO::getOrderId));
                log.info("orderList : o={} , {}", o);
                Integer deliveryDisplay=1;
                log.info("deliveryDisplay : o.getDeliveryType()={} , {}", o.getDeliveryType(),o.getOrderStatus());
                if(o!=null && o.getDeliveryType()!=null && o.getDeliveryType()==1 && o.getOrderStatus()==2 ){
                    deliveryDisplay=0;
                }else if (o!=null && o.getDeliveryType()!=null && o.getDeliveryType()==1 && o.getOrderStatus()==3
                        && o.getFinallyTime()!=null && LocalDateTime.now().isBefore(o.getFinallyTime())){
                    deliveryDisplay=0;
                }//完成时间+7天大于当前时间显示 流信息按钮是否显示，0 显示，1 不显示
                convert.setDeliveryDisplay(deliveryDisplay);
                return convert;
            }).collect(Collectors.toList());

            log.info("orderList records : {} ", records);
            return success(new PageResult<>(records, pageResult.getTotal(), pageResult.getTotalPage()));
        } else {
            return success(new PageResult<>(Collections.emptyList(), pageResult.getTotal(), pageResult.getTotalPage()));
        }
    }

    /**
     * 确认收货
     */
    @GlobalTransactional(name = "csc-order-receipt", rollbackFor = Exception.class)
    @PutMapping("/receipt/{orderId}")
    @Operation(summary = "根据订单子项id确认收货" , description = "根据订单子项id确认收货")
    public CommonResult<Object> receipt(@Valid @RequestBody AppOrderDeliveryReqVO reqVO) {
        log.info("[receipt] 当前 XID: {}", RootContext.getXID());
        log.info("[AppOrderV2Controller][receipt][reqVO]: {}",reqVO);
        OrderDO order = orderService.getOrderByOrderId(reqVO.getOrderId());
        List<OrderItemDO> itemDOS = orderItemService.getItemList(reqVO.getOrderItemId());
        List<OrderItemDO> itemList = itemDOS.stream().filter(e ->!e.getOrderStatus().equals(OrderStatusEnum.CONSIGNMENT.value())).collect(Collectors.toList());
        log.info("[AppOrderV2Controller][receipt][itemList]: {}",itemList);
        if (!CollectionUtils.isAnyEmpty(itemList)) {
            // 订单未发货，无法确认收货
            return CommonResult.error(ErrorCodeConstants.ORDER_NO_DELIVERY);
        }
        // 确认收货
        //修改子项的发货状态
        List<OrderUpdateDeliveryReqVO> deliveryReqVOS = reqVO.getOrderItemId().stream().map(id -> {
            OrderUpdateDeliveryReqVO vo = new OrderUpdateDeliveryReqVO();
            vo.setId(id);
            vo.setOrderStatus(OrderStatusEnum.SUCCESS.value());
            vo.setFinallyTime(LocalDateTime.now());
            return vo;
        }).collect(Collectors.toList());
        orderItemService.updateBatch(deliveryReqVOS);
        OrderDO orderDO = new OrderDO();
        orderDO.setId(reqVO.getOrderId())
               .setOrderStatus(OrderStatusEnum.SUCCESS.value())
               .setFinallyTime(LocalDateTime.now());
        orderService.updateOrderStatus(orderDO);

        // 创建分账任务  TODO 分布式事务
        CreateDivideWithOrderItemIdReqDTO reqDTO = new CreateDivideWithOrderItemIdReqDTO();
        reqDTO.setMerchantOrderId(order.getMerchantOrderId())
                .setOrderItemIds(reqVO.getOrderItemId());
        log.info("[AppOrderV2Controller][receipt][reqDTO]: {}",reqDTO);
        payOrderApi.createDivideByOrderItemId(reqDTO);
        orderReceiptProducer.sendOrderReceiptMessage(itemDOS);
        // 发送mq消息
        orderReceiptForHzhProducer.sendOrderReceiptMessage(order, getLoginUserId());
        return success(reqVO.getOrderId());
    }
    /**
     * 订单确认页-订单详情信息接口
     */
    @GetMapping("/orderDetail")
    @Operation(summary = "订单详情信息" , description = "根据订单号获取订单详情信息")
    @Parameter(name = "orderId", description = "订单号" , required = true)
    public CommonResult<AppOrderDetailRespVO> orderDetail(@RequestParam(value = "orderId") BigInteger orderId) {
        log.info("[AppOrderV2Controller][orderDetail][orderId]=={}",orderId);
        OrderDO orderDO = orderService.get(orderId);
        log.info("[AppOrderV2Controller][orderDetail][orderDO]=={}",orderDO);
        if(orderDO==null){
            return error(ErrorCodeConstants.ORDER_ITEM_NOT_EXISTS);
        }
        AppOrderDetailRespVO vo=OrderConvert.INSTANCE.convert03(orderDO);
        vo.setOrderId(orderDO.getId());
        List<BigInteger> shopIds = orderItemService.getShopIdByOrderId(orderId);
        List<ShopDetailRespDTO> shopDetails = shopDetailApi.getShopDetailList(shopIds).getCheckedData();
        Map<BigInteger, String> shopMap = CollectionUtils.convertMap(shopDetails, ShopDetailRespDTO::getId, ShopDetailRespDTO::getShopName);
        List<OrderItemDO> itemByOrderId = orderItemService.getItemByOrderId(orderId);
        // 按店铺分组
        Map<BigInteger, List<OrderItemDO>> listMap = itemByOrderId.stream().collect(Collectors.groupingBy(OrderItemDO::getShopId));
        List<OrderRespVO> orderRespVOS = listMap.entrySet().stream().map(s -> {
            OrderRespVO orderRespVO = OrderConvert.INSTANCE.convertVo(orderDO);
            orderRespVO.setShopId(s.getKey())
                .setShopName(shopMap.get(s.getKey()))
                .setOrderItems(OrderItemConvert.INSTANCE.convertVoList(s.getValue()));
            return orderRespVO;
        }).collect(Collectors.toList());
        vo.setOrderRespVO(orderRespVOS);
        //查订单详细地址
        OrderAddrDO orderAddrDO = orderAddrService.getAddrByOrderId(orderId);
        if(orderAddrDO==null){//查询默认地址
            MemberAddressRespDTO memberAddressRespDTO= memberAddressApi.getDefaultAddress(orderDO.getUserId().longValue()).getData();
            if(memberAddressRespDTO!=null){
                log.info("[AppOrderV2Controller][orderDetail][memberAddressRespDTO]=={},userId",memberAddressRespDTO,orderDO.getUserId().longValue());
                OrderAddrVO orderAddrVO= OrderAddrConvert.INSTANCE.convert03(memberAddressRespDTO);
                orderAddrVO.setMemberAddrId(String.valueOf(memberAddressRespDTO.getId()))
                            .setAddrDetail(memberAddressRespDTO.getDetailAddress())
                            .setConsignee(memberAddressRespDTO.getName());
                vo.setOrderAddr(orderAddrVO);
            }
        }else{
            vo.setOrderAddr(OrderAddrConvert.INSTANCE.convertVo(orderAddrDO).setOrderAddrId(orderAddrDO.getId()));
        }
        vo.setShopCartId(shopCartItemService.getShopCartItemIds(orderId));
        return success(vo);
    }
    /**
     * 已支付订单详情信息接口
     */
    @GetMapping("/orderItemsDetail")
    @Operation(summary = "订单详情信息" , description = "根据订单号获取订单详情信息")
    @Parameter(name = "orderItemIds", description = "订单项号" , required = true)
    public CommonResult<AppOrderItemDetailRespVO> getOrderItemDetail(@RequestParam(value = "orderItemIds") String orderItemIds) {
        log.info("[AppOrderV2Controller][getOrderItemDetail][reqVO]=={}",orderItemIds);
        AppOrderItemDetailRespVO vo=null;
        List<String> list= Arrays.stream(orderItemIds.split("-")).collect(Collectors.toList());
        List<BigInteger> orderItemId=list.stream().map(BigInteger::new ).collect(Collectors.toList());
        log.info("[AppOrderV2Controller][getOrderItemDetail][list]=={},{}",list,orderItemId);
        List<OrderItemDO> orderItemList=orderItemService.getItemList(orderItemId);


        if(!orderItemList.isEmpty()){
            OrderItemDO orderItemDO=orderItemList.get(0);
            OrderDO orderDO = orderService.get(orderItemDO.getOrderId());
            log.info("[AppOrderV2Controller][getOrderItemDetail][orderDO]=={}",orderDO);
            vo=OrderItemConvert.INSTANCE.convert02(orderItemDO);
            List<String> shoppingCardIds=new ArrayList<>();
            if(orderDO.getPayType()==1 || orderDO.getPayType()==2){
                List<BigInteger> cardIds=cardTransactionApi.getByOrderIds(Arrays.asList(orderDO.getId())).getCheckedData().stream().map(CardTransactionRespDTO::getCardId).distinct().collect(Collectors.toList());
                shoppingCardIds=cardApi.listByCardId(cardIds).getCheckedData().stream().map(CardRespDTO::getCardNumber).distinct().collect(Collectors.toList());
            }
            vo.setOrderId(orderDO.getId())
              .setPayTime(orderDO.getPayTime())
              .setOutTradeNo(orderDO.getOutTradeNo())
              .setShopId(orderItemDO.getShopId())
              .setShopName(shopDetailApi.getShopDetail(orderItemDO.getShopId()).getCheckedData().getShopName())
              .setOrderItems(OrderItemConvert.INSTANCE.convertVoList(orderItemList))
                //订单产品数量
              .setAllCount(orderItemList.stream().map(e -> e.getCount()).reduce(Integer::sum).get())
                //订单的总金额
              .setTotal(orderItemList.stream().map(OrderItemDO::getSpuTotalAmount).reduce(BigDecimal.ZERO,BigDecimal::add))
                //查订单详细地址
              .setOrderAddr(OrderAddrConvert.INSTANCE.convertVo(orderAddrService.getAddrByOrderId(orderItemDO.getOrderId())))
              //取购物卡的Id集合
              .setShoppingCardId(shoppingCardIds)
              .setActualAmount(orderItemList.stream()
                      .map(OrderItemDO::getSpuActualAmount)
                      .filter(Objects::nonNull)
                      .reduce(BigDecimal.ZERO, BigDecimal::add))
              .setCardPayAmount(orderItemList.stream()
                      .map(OrderItemDO::getCardPayAmount)
                      .filter(Objects::nonNull)
                      .reduce(BigDecimal.ZERO, BigDecimal::add));

        }
        return success(vo);
    }
    /**
     * 查询物流信息接口
     */
    @GetMapping("/logisticsDetail")
    @Operation(summary = "查询物流信息接口" , description = "根据物流单号查询物流信息接口")
    @Parameter(name = "orderItemId", description = "子订单Id" , required = true)
    @Parameter(name = "orderId", description = "大订单Id" , required = true)
    public CommonResult<AppLogisticsVO> getOrderItemDetail(@RequestParam(value = "orderId") BigInteger orderId,
                                                                     @RequestParam(value = "orderItemId") BigInteger orderItemId) {
        OrderAddrDO orderAddrDO=orderAddrService.getLogistics(orderId,orderItemId);
        AppLogisticsVO appLogisticsVO= new AppLogisticsVO();
        log.info("[receipt] orderAddrDO: {}",orderAddrDO);
        if(StringUtil.isNotEmpty(orderAddrDO.getLogisticsCom())){
            //查询第三方接口实时快递查询接口
            HttpResult httpResult=new Kuaidi100Util().queryTrack(customer,key,orderAddrDO.getLogisticsCom(),orderAddrDO.getLogisticsNum());
            log.info("[getOrderItemDetail][httpResult]:{}",httpResult);
            if(JSONObject.parseObject(httpResult.getBody()).get("status")!=null && JSONObject.parseObject(httpResult.getBody()).get("status").equals("200")){
                String json= JSONObject.parseObject(httpResult.getBody()).get("data").toString();
                Integer state=Integer.parseInt(JSONObject.parseObject(httpResult.getBody()).get("state").toString());
                Gson gson = new Gson();
                Type listType = new TypeToken<List<LogisticsVO>>(){}.getType();
                appLogisticsVO.setLogisticsList(gson.fromJson(json, listType));
                appLogisticsVO.setLogisticsStatus(LogisticsStatusEnum.getLable(state));
                appLogisticsVO.setLogisticsNum(orderAddrDO.getLogisticsNum());
                appLogisticsVO.setLogisticsComName(kuaiDi100CompanyCodeApi.getByCode(orderAddrDO.getLogisticsCom()).getData().getName());
            }else{
                String returnCode=String.valueOf(JSONObject.parseObject(httpResult.getBody()).get("returnCode"));
                if(StringUtil.isNotEmpty(returnCode)){
                    if(returnCode.equals("500")){
                        return error(ErrorCodeConstants.ORDER_WL_NODATA_ERROR);
                    }
                    if(returnCode.equals("400") ||returnCode.equals("408")){
                        return error(ErrorCodeConstants.ORDER_WL_COMPANY_ERROR);
                    }
                    if(returnCode.equals("501")|| returnCode.equals("502")
                            || returnCode.equals("503") || returnCode.equals("601")){
                        return error(ErrorCodeConstants.ORDER_WL_SYSTEM_ERROR);
                    }
                }
            }
        }
        return success(appLogisticsVO);
    }

    /**
     * 确认收货-查询物流状态是否已签收
     */
    @GlobalTransactional(name = "csc-order-receipt", rollbackFor = Exception.class)
    @PutMapping("/receiptCheck/{orderId}")
    @Operation(summary = "查询物流状态是否已签收" , description = "查询物流状态是否已签收")
    public CommonResult<Object> receiptCheck(@Valid @RequestBody AppOrderDeliveryReqVO reqVO) {
        log.info("[receiptCheck] 当前 XID: {}", RootContext.getXID());
        //判断，如果该物流单号是否标记签收状态（ischeck）不是已签收状态时，点击收货触发弹窗提示：“您的包裹好像还未签收，请检查后再确认收款”
        OrderAddrDO orderAddrDO = orderAddrService.getLogistics(reqVO.getOrderId(), reqVO.getOrderItemId().get(0));
        HttpResult httpResult = new Kuaidi100Util().queryTrack(customer, key, orderAddrDO.getLogisticsCom(), orderAddrDO.getLogisticsNum());
        log.info("[httpResult] 当前 httpResult: {}", httpResult);
        if (httpResult.getStatus() == 500) {
            return CommonResult.error(ErrorCodeConstants.ORDER_WL_ISCHECK_ERROR);
        }
        if(JSONObject.parseObject(httpResult.getBody()).get("status")!=null && JSONObject.parseObject(httpResult.getBody()).get("status").equals("200")){
            String json= JSONObject.parseObject(httpResult.getBody()).get("data").toString();
            log.info("[receiptCheck]",json);
            Integer state=Integer.parseInt(JSONObject.parseObject(httpResult.getBody()).get("state").toString());
            log.info("[state]",state);
            if(state!=3){
                return CommonResult.error(ErrorCodeConstants.ORDER_WL_ISCHECK_ERROR);
            }
        }

        return CommonResult.success();
    }

}
